/**
 *  学习目标：Todos 案例
 */
import React from 'react';
import './styles/base.css';
import './styles/index.css';

export default class App extends React.Component {
  // 2.1、先准备一个数组,并且设置初始值
  state = {
    // 5.1 声明type,表示当前选中的状态
    // 默认给all，type的值只能是all active cpmpleted
    type: localStorage.getItem('todo-type') || 'all',
    // 13.3从缓存中取出数据，用逻辑或设置空初始值

    list: JSON.parse(localStorage.getItem('todo-list')) || [],
  };

  // 13.1使用componentDidUpdate监听数据变化，获取到更新后的数据
  componentDidUpdate() {
    const { list, type } = this.state;
    // 13.2将数据保存到本地缓存，要转为string
    localStorage.setItem('todo-list', JSON.stringify(list));
    localStorage.setItem('todo-type', type);
  }

  // 15.1在App中定义全选的回调函数
  handelCheckAll = (e) => {
    console.log('checked', e.target.checked);
    const { list } = this.state;
    const newList = list.map((item) => {
      return {
        ...item,
        // 把之前isDone覆盖调
        isDone: e.target.checked,
      };
    });
    // 15.4实现全选计算逻辑
    this.setState({ list: newList });
  };

  // 11.1在APP中定义新增的回调函数
  handelAdd = (task) => {
    console.log('task这里  ----->  ', task);
    // 11.5完成新增逻辑
    this.setState({
      list: [{ id: Date.now(), task, isDone: false }, ...this.state.list],
    });
  };

  // 8.1在app中定义一个清除已完成的回调函数
  handelClear = () => {
    const { list } = this.state;
    console.log('点击事件触发');
    // 8.4完成清除已完成的处理,!item.isDone即是为false未完成的数据
    const NewList = list.filter((item) => !item.isDone);
    this.setState({ list: NewList });
  };

  // 6.1在App中声明一个可以修改type的函数
  handelUptype = (type) => {
    console.log('conme here  ----->  ', type);
    // 6.5实现修改type逻辑
    this.setState({ type: type });
  };

  //type一个修改list的回调函数，因为只有在app才能拿到this.state
  handelUpdateByid = (id) => {
    // console.log('come here', id);
    // 3.4完成更新计算逻辑
    const { list } = this.state;
    const Newlist = list.map((item) => {
      return {
        ...item,
        isDone: item.id === id ? !item.isDone : item.isDone,
      };
    });

    this.setState({
      list: Newlist,
    });
  };

  // 4.1在App中定义一个删除一条数据的回调函数
  handelDelByid = (id) => {
    // console.log('这里', id);
    const { list } = this.state;
    const NewList = list.filter((item) => {
      return item.id !== id;
    });
    this.setState({ list: NewList });
  };

  render() {
    const { list, type } = this.state;

    // 7.1定义计算属性showList，filter方法返回的布尔值
    const showList = list.filter((item) => {
      // 如果type为all，则返回true全部都要显示
      if (type === 'all') return true;
      // 如果type为active，则返回isDone为false的
      if (type === 'active') return !item.isDone;
      // 如果type为completed，则返回isDone为true的
      if (type === 'completed') return item.isDone;
    });

    // 14.1在App中定义一个计算属性isAll，通过计算每个小框的isdone是否为true得到布尔值
    // 如果所有isDone为true那么isAll为trye
    // 一个为false则为false
    //14.4添加判断，every当数组为空时要判断
    const isAll = !list.length
      ? false
      : list.every((item) => {
          return item.isDone;
        });

    return (
      <section className="todoapp">
        {/* 头部 */}
        {/* 11.2子传父，将回调传给header组件 */}
        <Header handelAdd={this.handelAdd}></Header>
        {/* 主体 */}
        {/* 2.2、通过父传子将list传给main组件 */}
        <Main
          // 7.2将showList传给main组件的props.list
          list={showList}
          // 3.2通过子传父，将回调函数传给main组件
          handelUpdateByid={this.handelUpdateByid}
          // 4.2通过子传父，将回调函数传给main组件
          handelDelByid={this.handelDelByid}
          // 14.2父传子将isAll传给main组件
          isAll={isAll}
          // 15.2子传父
          handelCheckAll={this.handelCheckAll}
        ></Main>
        {/* 底部 */}
        {/* 5.2通过父传子，把type传给footer组件 */}
        {/* 6.2子传父，将回调传给footer*/}
        {/* 8.2子传父 */}
        <Footer
          type={type}
          handelUptype={this.handelUptype}
          handelClear={this.handelClear}
          // 9.2将list通过父传子传到Footer中
          list={list}
        ></Footer>
      </section>
    );
  }
}

// 头部
class Header extends React.Component {
  // 10.1收集用户数据,受控组件
  state = {
    task: '',
  };

  // 11.3监听回车事件
  handleKeyDown = (e) => {
    const { handelAdd } = this.props;
    // 12.1 esc支持清除内容
    if (e.key === 'Escape') {
      this.setState({ task: '' });
      return;
    }
    if (e.key === 'Enter') {
      // 12.3非空判断，提示用户不可以输入纯空格字符
      if (!this.state.task.trim()) {
        alert('任务不能为空');
        return;
      }
      // 11.4回车事件中触发回调
      handelAdd(this.state.task);
      // 12.2新增后清除输入框
      this.setState({ task: '' });
    }
  };
  render() {
    const { task } = this.state;
    return (
      <header className="header">
        <h1>todos</h1>
        <input
          // 10.2state控制value
          value={task}
          // 10.3onchange和setstate更新数据
          onChange={(e) => this.setState({ task: e.target.value })}
          onKeyDown={this.handleKeyDown}
          className="new-todo"
          placeholder="需要做什么"
          autoFocus
        />
      </header>
    );
  }
}
// 主要部分
class Main extends React.Component {
  render() {
    const { list, handelUpdateByid, handelDelByid, isAll, handelCheckAll } =
      this.props;
    return (
      <section className="main">
        <input
          // 14.3将isAll控制全选按钮的checked属性
          checked={isAll}
          id="toggle-all"
          className="toggle-all"
          type="checkbox"
          // 15.3子组件调用回调函数
          onChange={handelCheckAll}
        />
        <label htmlFor="toggle-all">全选</label>
        <ul className="todo-list">
          {/* 2.3、在main组件中，通过列表渲染生成任务 */}
          {list.map((item) => {
            return (
              // 2.4、设置选中和样式
              <li className={item.isDone ? 'completed' : ''} key={item.id}>
                <div className="view">
                  <input
                    // 3.3在main组件中，onchange时调用回调函数，并传参id，箭头函数传参，onchange是获取输入框的值

                    onChange={() => {
                      handelUpdateByid(item.id);
                    }}
                    className="toggle"
                    type="checkbox"
                    checked={item.isDone}
                  />
                  <label>{item.task}</label>
                  {/* 4.3子组件内调用回调函数，并且传参 */}
                  <button
                    onClick={() => handelDelByid(item.id)}
                    className="destroy"
                  ></button>
                </div>
              </li>
            );
          })}
        </ul>
      </section>
    );
  }
}
// 底部
// 9.1将footer改造为函数组件
function Footer({ type, handelUptype, handelClear, list }) {
  // 9.3在footer中定义计算属性restLength
  const restLength = list.filter((item) => {
    return !item.isDone;
  }).length;
  // console.log(restLength);
  return (
    <footer className="footer">
      <span className="todo-count">
        {/* 9.4使用插值表达式显示剩余数量 */}
        <strong>{restLength}</strong> 剩余
      </span>
      <ul className="filters">
        <li>
          {/* 排他判断技术 */}
          {/* 当type为all时，加上selected */}
          {/* 5.3通过对比type的值，给a标签加上classname */}
          {/* 6.3 点击事件触发回调函数，并且传参type*/}
          <a
            onClick={() => handelUptype('all')}
            className={type === 'all' ? 'selected' : ''}
            href="#/"
          >
            全部
          </a>
        </li>
        <li>
          {/* 当type为active时，加上selected */}
          <a
            onClick={() => handelUptype('active')}
            className={type === 'active' ? 'selected' : ''}
            href="#/active"
          >
            未完成
          </a>
        </li>
        <li>
          {/* 当type为completed时，加上selected */}
          <a
            onClick={() => handelUptype('completed')}
            className={type === 'completed' ? 'selected' : ''}
            href="#/completed"
          >
            已完成
          </a>
        </li>
      </ul>
      <button
        // 8.3添加点击事件
        className="clear-completed"
        onClick={handelClear}
      >
        清除已完成
      </button>
    </footer>
  );
}
